﻿/*
 * ------------------------------------
 *    Rodeo Game Engine
 *    Rodeo Renderer Module
 *    CGShaders.cpp - source file
 *    Copyright(c) Marcin Goryca
 * ------------------------------------
 */
#include "..\include\renderer\cgshaders.h"

namespace rodeorenderer 
{
rodeocore::ui CGShaders::loadShaderFromFile(const char* file, rodeocore::ShaderType st)
{
    switch(st)
    {
    case rodeocore::RODEO_VS: //VERTEX_SHADER (RODEO_VS)
        {
            setVertexProgramFile(file);
            return vertex_shader_;
        }
        break;

    case rodeocore::RODEO_FS: //FRAGMENT_SHADER (RODEO_FS)
        {
            setFragmentProgramFile(file);
            return fragment_shader_;
        }
        break;

    default:
        //TODO
        //Exception Handling
        return 0;
        break;
    }
}

// ---- //
void CGShaders::loadVertexShader(std::string filename)
{
    //setVertexShader(
}

// ---- //
void CGShaders::init()
{
    initCG();
}

// ---- //
void CGShaders::useShaderProgram(rodeocore::ui shader_program)
{
   //cgVertexShaderProgram_ = reinterpret_cast<CGprogram>(shader_program);
}

// ---- //
void CGShaders::initCG()
{
    context_ = cgCreateContext();
    checkForError("Creating CG Context...");
    vs_profile_ = cgGLGetLatestProfile(CG_GL_VERTEX);
    cgGLSetOptimalOptions(vs_profile_);
    checkForError("Selecting Vertex Shader Profile...");

    vs_program_ = cgCreateProgramFromFile
        (
            context_,
            CG_SOURCE, 
            vs_filename_.c_str(),
            vs_profile_,
            vs_entry_.c_str(),
            NULL
        );
    checkForError("Creating Vertex Shader from file...");
    cgGLLoadProgram(vs_program_);
    checkForError("Loading Vertex Shader program...");

    fs_profile_ = cgGLGetLatestProfile(CG_GL_FRAGMENT);
    cgGLSetOptimalOptions(fs_profile_);
    checkForError("Selecting Fragment Shader Profile...");

    fs_program_ = cgCreateProgramFromFile
        (
            context_,
            CG_SOURCE,
            fs_filename_.c_str(),
            fs_profile_,
            fs_entry_.c_str(),
            NULL
        );
    checkForError("Creating Fragment Shader from file...");
    cgGLLoadProgram(fs_program_);
    checkForError("Loading Fragment Shader Program...");
}

// ---- //
//void CGShaders::initCG(const char* pfn, const char* vpn)
//{
//    cgContext_ = cgCreateContext();
//    cgVertexShaderProfile_ = cgGLGetLatestProfile(CG_GL_VERTEX);
//    cgGLSetOptimalOptions(cgVertexShaderProfile_);
//
//    setCGVertexProgramFileName(pfn);
//    setCGVertexProgramName(vpn);
//
//    cgVertexShaderProgram_ = cgCreateProgramFromFile
//        (
//            cgContext_,
//            CG_SOURCE, 
//            cgVertexShaderProgramFileName_,
//            cgVertexShaderProfile_,
//            cgVertexProgramName_,
//            NULL
//        );
//
//    cgGLLoadProgram(cgVertexShaderProgram_);
//}

// ---- //
void CGShaders::bindProgram(CGprogram program)
{
    cgGLBindProgram(program);
}

// ---- //
void CGShaders::enableProfile(CGprofile profile)
{
    cgGLEnableProfile(profile);
}

// ---- //
void CGShaders::disableProfile(CGprofile profile)
{
    cgGLDisableProfile(profile);
}

// ---- //
void CGShaders::initCG(std::string vertex_shader_filename, std::string vertex_shader_entry_point, std::string fragment_shader_filename, std::string fragment_shader_entry_point)
{
    context_ = cgCreateContext();
    cgGLRegisterStates(context_);
    cgGLSetManageTextureParameters(context_, CG_TRUE);
    vs_profile_ = cgGLGetLatestProfile(CG_GL_VERTEX);
    cgGLSetOptimalOptions(vs_profile_);

    setVSFilename(vertex_shader_filename);
    setVSEntryPoint(vertex_shader_entry_point);

    vs_program_ = cgCreateProgramFromFile
        (
            context_,
            CG_SOURCE, 
            getVSFilename().c_str(),
            vs_profile_,
            getVSEntryPoint().c_str(),
            NULL
        );

    cgGLLoadProgram(vs_program_);

    setFSFilename(fragment_shader_filename);
    setFSEntryPoint(fragment_shader_entry_point);

    fs_profile_ = cgGLGetLatestProfile(CG_GL_FRAGMENT);
    cgGLSetOptimalOptions(fs_profile_);
 
     fs_program_ = cgCreateProgramFromFile(
      getContext(),												
      CG_SOURCE,
      getFSFilename().c_str(),
      getFSProfile(),
      getFSEntryPoint().c_str(),
      NULL);
    cgGLLoadProgram(fs_program_);
}

// ---- //
void CGShaders::enableTextureParameter(CGparameter param)
{
    cgGLEnableTextureParameter(param);
}

// ---- //
void CGShaders::disableTextureParameter(CGparameter param)
{
    cgGLDisableTextureParameter(param);
}

// [PRIVATE] //
void CGShaders::checkForError(std::string message)
{
    CGerror error;
    const char* last_error = cgGetLastErrorString(&error);

    if(error != CG_NO_ERROR)
    {
        MessageBox(NULL, last_error, message.c_str(), MB_OK);

        if(error == CG_COMPILER_ERROR)
        {
            MessageBox(NULL, cgGetLastListing(getContext()), "RODEO", MB_OK);
        }
        exit(1);
    }
}
}    // end of rodeorenderer namespace